#ifndef AECMODELER_INC_PLANE_H
#define AECMODELER_INC_PLANE_H

#include "zpoint3d.h"

AECMODELER_NAMESPACE_BEGIN


class DllImpExp UePlane
{
public:

    UePlane()                                 : normal(UeVector3d::kNull), d(0) {}
    UePlane(UeVector3d nn, double dd)           : normal(nn), d(dd)             {}
    UePlane(UePoint3d, UeVector3d); 
    UePlane(const UePoint3d&, const UePoint3d&,  const UePoint3d&);
    UePlane(const UePoint3d&, const UeVector3d&, const UeVector3d&);

    // Create plane from a polygon of vertices (n >=3). All polygon vertices
    // are used to calculate the plane coefficients to make the formula
    // symetrical.
    //
    UePlane(const UePoint3d plg[], int n);

    // The plane normal is given, just calculate the 'd' parameter from all 
    // polygon vertices.
    //
    UePlane(const UePoint3d plg[], int n, const UeVector3d& normal);

    // Create a plane from the given set of coplanar points. Returns a null 
    // plane if the points do not define a plane. Unlike the Plane constructor
    // that takes a closed polygon, the set of points here is just any set of
    // points and the method tries to do some kind of a best fit plane from 
    // them
    //
    static UePlane fromPoints(const UePoint3d pts[], int pointCount, bool checkPlanarity);

    UePlane    operator -()                const { return UePlane(-normal, -d); }
    double   dist      (UePoint3d p)       const { return p % normal + d; }
    UePoint3d  project   (const UePoint3d& ) const;
    UeVector3d project   (const UeVector3d&) const;
    UeLine3d   project   (const UeLine3d&  ) const;

    UeLine3d   operator* (const UePlane&   ) const;
    UePoint3d  operator* (const UeLine3d&  ) const;

    bool     isValid   () const { return fabs(normal.length() - 1) < UeEpsNor(); }

    bool     isEqual   (UePlane) const;

    void     orthoPlane(int& i1, int& i2)          const;
    void     orthoPlane(int& i1, int& i2, int& i3) const;

    // Public data members
    //    
    UeVector3d normal;
    double   d;

}; // class Plane



inline UePlane::UePlane(UePoint3d p, UeVector3d norm)
  : normal(norm)
{
    normal = normal.normalize();
    d = -p % normal;
}


inline bool UePlane::isEqual(UePlane pla) const 
{ 
    return normal.isEqual(pla.normal) && fabs(d-pla.d) <= UeEpsAbs(); 
}


AECMODELER_NAMESPACE_END
#endif
